/*
 * Copyright (c) SCUT. 2022. All rights reserved.
 * Description: The main of function test.
 * Author: linhouzhong
 * Create: 2022-06-26
 */

// gfortran main.c func_test.c creat_matrix.c _pot02.o SYSV_RK.c SYTF2_RK.c
// SYTRF_RK.c SYTRS_3.c LASYF_RK.c ilaenv.c   -o main -L /usr/local/lapacke/lib
// -llapack  -L /usr/local/cblas -lcblas -lblas -L /usr/local/kml/lib -lkservice
// -D SINGLE -fopenmp
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "func_test.h"

int main(int argc, char* argv[]) {
    funcTdataType *A, *A1, *E, *B1, *B2, *B3, *B4, *W;
    funcTdataAccu* W1;
    int* ipiv;
    double N = 40000;
    double NRHS = N;
    int size = sizeof(funcTdataType);
    if (((A = (funcTdataType*)malloc(size * N * N)) == NULL) ||
        ((A1 = (funcTdataType*)malloc(size * N * N)) == NULL) ||
        ((E = (funcTdataType*)malloc(size * N)) == NULL) ||
        ((B1 = (funcTdataType*)malloc(size * N * NRHS)) == NULL) ||
        ((B2 = (funcTdataType*)malloc(size * N * NRHS)) == NULL) ||
        ((B4 = (funcTdataType*)malloc(size * N * NRHS)) == NULL) ||
        ((B3 = (funcTdataType*)malloc(size * N * NRHS)) == NULL) ||
        ((W = (funcTdataType*)malloc(size * N * N)) == NULL) ||
        ((W1 = (funcTdataAccu*)malloc(sizeof(funcTdataAccu) * N * N)) ==
         NULL) ||
        ((ipiv = (int*)malloc(sizeof(int) * N)) == NULL)) {
        printf("malloc error!\n");
        return -1;
    }
    // *** result test ***
    printf("*** reult test ***\n");
    srand((unsigned)time(NULL));
    char scale;
    int times;
    // test small scale
    scale = 's';
    times = rand() % 11 + 20;  //[20,30]
    printf("test small scale,test times: %d \n", times);
    _FuncTest(times, scale, A, A1, E, B1, B2, B3, B4, W, W1, ipiv);
    // test middle scale
    scale = 'm';
    times = rand() % 11 + 10;  //[10,20]
    printf("test middle scale,test times: %d \n", times);
    _FuncTest(times, scale, A, A1, E, B1, B2, B3, B4, W, W1, ipiv);
    // test big scale
    scale = 'b';
    times = rand() % 5 + 1;  //[1,5]
    printf("test big scale,test times: %d \n", times);
    _FuncTest(times, scale, A, A1, E, B1, B2, B3, B4, W, W1, ipiv);
    free(A);
    free(A1);
    free(E);
    free(B1);
    free(B2);
    free(B3);
    free(B4);
    free(W);
    free(W1);
    free(ipiv);

    // *** exception test ***
    printf("\n*** exception test ***\n");
    // parameter exception
    int N2, NRHS2;
    funcTdataType *A_2, *E_2, *B_2, *W_2;
    int *ipiv_2, info_2;
    char uplo;
    size = sizeof(funcTdataType);
    uplo = '/';
    N2 = 1;
    NRHS2 = 1;
    if (((A_2 = (funcTdataType*)malloc(size * N2 * N2)) == NULL) ||
        ((B_2 = (funcTdataType*)malloc(size * N2 * NRHS2)) == NULL) ||
        ((E_2 = (funcTdataType*)malloc(size * N2)) == NULL) ||
        ((W_2 = (funcTdataType*)malloc(size * N2 * N2)) == NULL) ||
        ((ipiv_2 = (int*)malloc(sizeof(int) * N2)) == NULL)) {
        printf("malloc error!\n");
        return 0;
    }
    SYSV_RK(&uplo, &N2, &NRHS2, A_2, &N2, E_2, ipiv_2, B_2, &N2, W_2, &N2,
            &info_2);
    uplo = 'U';
    int neg_one = -1;
    SYSV_RK(&uplo, &neg_one, &NRHS2, A_2, &N2, E_2, ipiv_2, B_2, &N2, W_2, &N2,
            &info_2);
    int two = 2, zero = 0;
    SYSV_RK(&uplo, &zero, &neg_one, A_2, &N2, E_2, ipiv_2, B_2, &N2, W_2, &N2,
            &info_2);
    SYSV_RK(&uplo, &two, &zero, A_2, &N2, E_2, ipiv_2, B_2, &two, W_2, &N2,
            &info_2);
    SYSV_RK(&uplo, &two, &zero, A_2, &two, E_2, ipiv_2, B_2, &N2, W_2, &N2,
            &info_2);
    SYSV_RK(&uplo, &zero, &zero, A_2, &N2, E_2, ipiv_2, B_2, &N2, W_2, &zero,
            &info_2);
    int neg_two = -2;
    SYSV_RK(&uplo, &zero, &zero, A_2, &N2, E_2, ipiv_2, B_2, &N2, W_2, &neg_two,
            &info_2);

    free(A_2);
    free(B_2);
    free(E_2);
    free(W_2);
    free(ipiv_2);

    // null pointer
    printf("exception test\n");
    nullptr_test(10, 10);

    return 0;
}